/************************************************************************/
/*	Copyright (C) 1999 RouterWare, Inc.     							*/
/*	Unpublished - rights reserved under the Copyright Laws of the		*/
/*	United States.  Use, duplication, or disclosure by the 				*/
/*	Government is subject to restrictions as set forth in 				*/
/*	subparagraph (c)(1)(ii) of the Rights in Technical Data and 		*/
/*	Computer Software clause at 252.227-7013.							*/
/*	RouterWare, Inc., 3961 MacArthur Blvd. Suite 212, Newport Beach, CA	*/
/************************************************************************/
#if !defined (__IP_MESSAGE_IF_H__)
#define __IP_MESSAGE_IF_H__
/****************************************************************************************************************************/
#define NUMBER_OF_BITS_IN_BYTE						8
#define MAX_OPTION_DATA_LENGTH						38
#define	PADDING_BETWEEN_OPTIONS						1
#define	PADDING_AT_THE_END_OF_OPTIONS				0

typedef UINT IP_TYPE_OF_SERVICE;
/****************************************************************************************************************************/
/* class : IP_MESSAGE */
typedef enum IP_TRANSPORT_PROTOCOL
{
	ICMP_PROTOCOL										= 1,
	IGMP_PROTOCOL										= 2,
	TCP_PROTOCOL										= 6,
	UDP_PROTOCOL										= 17,
	ESP_PROTOCOL										= 50,
	AH_PROTOCOL											= 51,
	OSPF_PROTOCOL										= 89,
	TRANSPORT_PROTOCOL_ANY							= 0xffff
} IP_TRANSPORT_PROTOCOL;
/**********************************************************************************************/
typedef enum IP_OPTION_TYPE
{
	IP_RECORD_ROUTE_TYPE								= 7,
	IP_INTERNET_TIMESTAMP_TYPE						= 68,
	IP_SECURITY_TYPE									= 130,
	IP_LOOSE_SOURCE_AND_RECORD_ROUTE_TYPE		= 131, 
	IP_STREAM_IDENTIFIER_TYPE						= 136,
	IP_STRICT_SOURCE_AND_RECORD_ROUTE_TYPE		= 137
} IP_OPTION_TYPE;
/**********************************************************************************************/
typedef struct IP_OPTION
{
	IP_OPTION_TYPE				option_type;
	UINT							option_data_length;
	BYTE							option_data [MAX_OPTION_DATA_LENGTH];
} IP_OPTION;
/* ************************************************************************************************************************ */
typedef struct IP_MESSAGE
{
	UINT							header_length;
	IP_TYPE_OF_SERVICE				type_of_service;
	UINT							total_length;
	UINT							datagram_identifier;
	UINT							dont_fragment_flag;
	UINT							more_fragment_flag;
	UINT							fragment_offset;
	UINT							time_to_live;
	IP_TRANSPORT_PROTOCOL			transport_protocol;	
	UINT							checksum;
	UINT							source_address;
	UINT							destination_address;
	RW_CONTAINER*					p_ip_option_list;					

	bool							(*fp_serialize) (struct IP_MESSAGE* p_ip_message, RW_PACKET_HANDLE* p_payload);
		/* ownership of packet_handle is passed to the caller */
	bool							(*fp_is_fully_deserialized) (struct IP_MESSAGE* p_ip_message);

	RW_PACKET_HANDLE			payload;
} IP_MESSAGE;

IP_MESSAGE* ip_message_create (void);
bool ip_message_destroy (IP_MESSAGE* p_ip_message);
bool ip_message_copy (IP_MESSAGE* p_ip_new_message, IP_MESSAGE* p_ip_original_message);
bool ip_option_list_copy (RW_CONTAINER* p_new_ip_option_list, RW_CONTAINER* p_original_ip_option_list);
bool ip_message_deserialize (IP_MESSAGE* p_ip_message, RW_PACKET_HANDLE payload);
	/* ownership of packet_handle is passed to this function */
IP_MESSAGE* ip_message_fully_deserialize (IP_MESSAGE* p_ip_message);
UINT ip_message_get_max_serialized_header_size (IP_MESSAGE* p_ip_message);
UINT ip_message_get_max_serialized_packet_size (IP_MESSAGE* p_ip_message);
/****************************************************************************************************************************/
#if 0

typedef struct TCP_MESSAGE
{
	IP_MESSAGE				parent;
	UINT					source_port_number;
	UINT					destination_port_number;
	UINT					sequence_number;
	UINT					acknowledgement_number;
	UINT					data_offset;
	bool					urg_flag;
	bool					ack_flag;
	bool					psh_flag;
	bool					rst_flag;
	bool					syn_flag;
	bool					fin_flag;
	UINT					window;
	UINT					urgent_pointer;
					
	/* And some more message header fields */
} TCP_MESSAGE;

TCP_MESSAGE* tcp_message_create (void);
bool tcp_message_destroy (TCP_MESSAGE* p_tcp_message);
bool tcp_message_copy (TCP_MESSAGE* p_tcp_new_message, TCP_MESSAGE* p_tcp_original_message);
/************************************************************************************************************************* */
typedef struct UDP_MESSAGE UDP_MESSAGE;
struct UDP_MESSAGE
{
	IP_MESSAGE parent;
	/* And some more message header fields */
};
UDP_MESSAGE* udp_message_create (void);
bool udp_message_destroy (UDP_MESSAGE* p_udp_message);
bool udp_message_copy (UDP_MESSAGE* p_udp_new_message, UDP_MESSAGE* p_udp_original_message);

#endif
/* ************************************************************************************************************************ */
#define ICMP_MESSAGE_FIXED_HEADER_SIZE			4

typedef enum ICMP_MESSAGE_TYPE
{
	ICMP_ECHO_REPLY_TYPE								= 0,
	ICMP_DESTINATION_UNREACHABLE_TYPE			= 3, 
	ICMP_SOURCE_QUENCH_TYPE							= 4,
	ICMP_REDIRECT_TYPE								= 5,
	ICMP_ECHO_REQUEST_TYPE 							= 8,
	ICMP_TIME_EXCEEDED_TYPE							= 11,
	ICMP_PARAMETER_PROBLEM_TYPE 					= 12,
	ICMP_TIMESTAMP_TYPE								= 13,
	ICMP_TIMESTAMP_REPLY_TYPE						= 14,
	ICMP_INFO_REQUEST_TYPE							= 15,
	ICMP_INFO_REPLY_TYPE								= 16,
	ICMP_INVALID_TYPE									= 17
} ICMP_MESSAGE_TYPE;

typedef enum ICMP_MESSAGE_CODE
{
	ICMP_CODE_DEFAULT									= 0,
	ICMP_CODE_NET_UNREACHABLE						= 0,
	ICMP_CODE_HOST_UNREACHABLE						= 1,
	ICMP_CODE_PROTOCOL_UNREACHABLE				= 2,
	ICMP_CODE_PORT_UNREACHABLE						= 3,
	ICMP_CODE_FRAGMENTATION_NEEDED				= 4,
	ICMP_CODE_SOURCE_ROUTE_FAILED					= 5,
	ICMP_CODE_REDIRECT_FOR_NETWORK				= 0,
	ICMP_CODE_REDIRECT_FOR_HOST					= 1,
	ICMP_CODE_REDIRECT_FOR_TOS_AND_NETWORK		= 2,
	ICMP_CODE_REDIRECT_FOR_TOS_AND_HOST			= 3,
	ICMP_CODE_TTL_EXCEEDED							= 0,
	ICMP_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEXDED		= 1
} ICMP_MESSAGE_CODE;

typedef struct ICMP_MESSAGE
{
	IP_MESSAGE										parent;
	ICMP_MESSAGE_TYPE								type;
	ICMP_MESSAGE_CODE								code;
} ICMP_MESSAGE;

ICMP_MESSAGE* icmp_message_create (void);
bool icmp_message_destroy (ICMP_MESSAGE* p_icmp_message);
bool icmp_message_copy (ICMP_MESSAGE* p_icmp_new_message, ICMP_MESSAGE* p_icmp_original_message);
/* ************************************************************************************************************************ */
/*ICMP Code: DESTINATION_UNREACHABLE, TIME_EXCEEDED, */
typedef struct ICMP_COMMON_MESSAGE
{
	ICMP_MESSAGE									parent;
	BYTE*												p_ip_header;
	UINT												header_length;
} ICMP_COMMON_MESSAGE;

ICMP_COMMON_MESSAGE* icmp_common_message_create (void);
bool icmp_common_message_destroy (ICMP_COMMON_MESSAGE* p_icmp_common_message);
bool icmp_common_message_copy (ICMP_COMMON_MESSAGE* p_icmp_common_new_message, ICMP_COMMON_MESSAGE* p_icmp_common_original_message);
/* ************************************************************************************************************************ */
/*ICMP Code: REDIRECT*/
typedef struct ICMP_REDIRECT_MESSAGE
{
	ICMP_MESSAGE									parent;
	UINT												gateway_ip_address;
	BYTE*												p_ip_header;
	UINT												header_length;
} ICMP_REDIRECT_MESSAGE;

ICMP_REDIRECT_MESSAGE* icmp_redirect_message_create (void);
bool icmp_redirect_message_destroy (ICMP_REDIRECT_MESSAGE* p_redirect_icmp_message);
bool icmp_redirect_message_copy (ICMP_REDIRECT_MESSAGE* p_icmp_redirect_new_message, ICMP_REDIRECT_MESSAGE* p_icmp_redirect_original_message);
/* ************************************************************************************************************************ */
/*ICMP Code: PARAMETER PROBLEM*/
typedef struct ICMP_PARAMETER_PROBLEM_MESSAGE
{
	ICMP_MESSAGE									parent;
	UINT												pointer;
	BYTE*												p_ip_header;
	UINT												header_length;
} ICMP_PARAMETER_PROBLEM_MESSAGE;

ICMP_PARAMETER_PROBLEM_MESSAGE* icmp_parameter_problem_message_create (void);
bool icmp_parameter_problem_message_destroy (ICMP_PARAMETER_PROBLEM_MESSAGE* p_parameter_problem_icmp_message);
bool icmp_parameter_problem_message_copy (ICMP_PARAMETER_PROBLEM_MESSAGE* p_parameter_problem_icmp_new_message,
										  ICMP_PARAMETER_PROBLEM_MESSAGE* p_parameter_problem_icmp_old_message);
/* ************************************************************************************************************************ */
/*ICMP Code: ECHO AND ECHO REPLY*/
typedef struct ICMP_ECHO_MESSAGE
{
	ICMP_MESSAGE									parent;
	UINT												identifier;
	UINT												sequence_number;
	BYTE*												p_data;
	UINT												data_length;
} ICMP_ECHO_MESSAGE;

ICMP_ECHO_MESSAGE* icmp_echo_message_create (void);
bool icmp_echo_message_destroy (ICMP_ECHO_MESSAGE* p_echo_icmp_message);
bool icmp_echo_message_copy (ICMP_ECHO_MESSAGE* p_icmp_echo_new_message, ICMP_ECHO_MESSAGE* p_icmp_echo_original_message);
/* ************************************************************************************************************************ */
/*ICMP Code: TIMESTAMP AND TIMESTAMPE REPLY*/
typedef struct ICMP_TIMESTAMP_MESSAGE
{
	ICMP_MESSAGE									parent;
	UINT												identifier;
	UINT												sequence_number;
	UINT												originate_timestamp;
	UINT												receive_timestamp;
	UINT												transmit_timestamp;
} ICMP_TIMESTAMP_MESSAGE;

ICMP_TIMESTAMP_MESSAGE* icmp_timestamp_message_create (void);
bool icmp_timestamp_message_destroy (ICMP_TIMESTAMP_MESSAGE* p_timestamp_icmp_message);
bool icmp_timestamp_message_copy (ICMP_TIMESTAMP_MESSAGE* p_icmp_timestamp_new_message, ICMP_TIMESTAMP_MESSAGE* p_icmp_timestamp_original_message);
/* ************************************************************************************************************************ */
/*ICMP Code: INFORMATION REQUEST AND INFORMATION REPLY*/
typedef struct ICMP_INFO_MESSAGE
{
	ICMP_MESSAGE									parent;
	UINT												identifier;
	UINT												sequence_number;
} ICMP_INFO_MESSAGE;

ICMP_INFO_MESSAGE* icmp_info_message_create (void);
bool icmp_info_message_destroy (ICMP_INFO_MESSAGE* p_info_icmp_message);
bool icmp_info_message_copy (ICMP_INFO_MESSAGE* p_icmp_info_new_message, ICMP_INFO_MESSAGE* p_icmp_info_original_message);
/* ************************************************************************************************************************ */
#endif /* __IP_MESSAGE_IF_H__ */

